home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / IFC_112 / netscape / application / ScrollView.java < prev    next >
Encoding:
Text File  |  1999-05-28  |  24.3 KB  |  738 lines  |  [TEXT/CWIE]

  1. // ScrollView.java
  2. // By Ned Etcode
  3. // Copyright 1995, 1996, 1997 Netscape Communications Corp. All rights reserved.
  4.  
  5. package netscape.application;
  6.  
  7. import java.lang.Math;
  8. import netscape.util.*;
  9.  
  10.  
  11. /** View subclass that manages the display of a larger View. This View,
  12.   * the ScrollView's "contentView," is a subview of the ScrollView. A
  13.   * ScrollView can be told to essentially move its contentView's origin
  14.   * to different locations, resulting in different portions of the contentView
  15.   * becoming visible through the ScrollView's bounds. A scroll command
  16.   * causes the entire visible portion of the contentView to be redrawn. If
  17.   * the ScrollView has been configured to use a drawing buffer, it uses the
  18.   * buffer to hold the visible portion of the contentView. Scroll requests
  19.   * copy as much as possible from the buffer, and ask the contentView to
  20.   * redraw just the newly exposed regions. Whenever a ScrollView moves
  21.   * its contentView, it sends a message to all of its ScrollBars so that
  22.   * they can update their knob size and position. A ScrollView maintains a
  23.   * Vector of ScrollBars (or other objects) wishing to receive these
  24.   * notifications. ScrollView's <b>addScrollBar()</b> and
  25.   * <b>removeScrollBar()</b> methods manage this Vector. ScrollGroups typically
  26.   * instantiate ScrollViews, but need not be. You can create a
  27.   * ScrollView and a ScrollBar, and connect them by calling the ScrollBar's
  28.   * <b>setScrollableObject()</b> method and ScrollView's <b>addScrollBar()</b>
  29.   * method.
  30.   * @see ScrollBar
  31.   * @see ScrollGroup
  32.   * @see Scrollable
  33.   * @note 1.0 draws to dirtyRect
  34.   */
  35.  
  36.  
  37. public class ScrollView extends View implements Scrollable {
  38.     View        contentView;
  39.     Color       backgroundColor;
  40.     Rect        clipRect;
  41.     Vector      scrollBars;
  42.     boolean     transparent = false;
  43.  
  44.     private boolean     scrollBarUpdatesEnabled = true;
  45.  
  46.     final static String         CONTENTVIEW_KEY = "contentView",
  47.                                 BACKGROUNDC_KEY = "backgroundColor",
  48.                                 SCROLLERS_KEY = "scrollBars",
  49.                                 SCROLLERUPDATES_KEY = "scrollBarUpdatesEnabed",
  50.                                 TRANSPARENT_KEY = "transparent";
  51.  
  52.  
  53.     /** Constructs a ScrollView with origin (<b>0</b>, <b>0</b>) and zero
  54.       * width and height.
  55.       */
  56.     public ScrollView() {
  57.         this(0, 0, 0, 0);
  58.     }
  59.  
  60.     /** Constructs a ScrollView with bounds <B>rect</B>.
  61.       */
  62.     public ScrollView(Rect rect) {
  63.         this(rect.x, rect.y, rect.width, rect.height);
  64.     }
  65.  
  66.     /** Constructs a ScrollView with bounds
  67.       * (<B>x</B>, <B>y</B>, <B>width</B>, <B>height</B>).
  68.       */
  69.     public ScrollView(int x, int y, int width, int height) {
  70.         super(x, y, width, height);
  71.  
  72.         scrollBars = new Vector();
  73.  
  74.         backgroundColor = Color.lightGray;
  75.  
  76.         setHorizResizeInstruction(View.WIDTH_CAN_CHANGE);
  77.         setVertResizeInstruction(View.HEIGHT_CAN_CHANGE);
  78.     }
  79.  
  80.     /** Overridden to prevent multiple Views from being added to the
  81.       * ScrollView.  Use the <b>setContentView()</b> method to set the View
  82.       * scrolled by the ScrollView.
  83.       * @see #setContentView
  84.       */
  85.     public void addSubview(View aView) {
  86.         subviews().removeAllElements();
  87.         super.addSubview(aView);
  88.     }
  89.  
  90.     /** Sets the View scrolled by the ScrollView to <b>aView</b>. */
  91.     public void setContentView(View aView) {
  92.         if (contentView != null) {
  93. //            contentView.setWantsAutoscrollEvents(false);
  94.             contentView.removeFromSuperview();
  95.         }
  96.  
  97.         contentView = aView;
  98.         if (contentView != null) {
  99.             contentView.moveTo(0, 0);
  100.             addSubview(contentView);
  101. //            contentView.setWantsAutoscrollEvents(true);
  102.         }
  103.  
  104.         updateScrollBars();
  105.     }
  106.  
  107.     /** Returns the View scrolled by the ScrollView.
  108.       * @see #setContentView
  109.       */
  110.     public View contentView() {
  111.         return contentView;
  112.     }
  113.  
  114.     /** Overridden to return the ScrollView's contentView's cursor for this
  115.       * point.
  116.       */
  117.     public int cursorForPoint(int x, int y) {
  118.         Point        tmpPoint;
  119.         int        cursor;
  120.  
  121.         if (contentView == null) {
  122.             return ARROW_CURSOR;
  123.         }
  124.  
  125.         tmpPoint = Point.newPoint(x, y);
  126.         convertPointToView(contentView, tmpPoint, tmpPoint);
  127.  
  128.         cursor = contentView.cursorForPoint(tmpPoint.x, tmpPoint.y);
  129.  
  130.         Point.returnPoint(tmpPoint);
  131.  
  132.         return cursor;
  133.     }
  134.  
  135.    /** Returns the ScrollView's background Color. If not transparent, the
  136.      * ScrollView uses the background Color to paint the portions of itself
  137.      * not covered by its contentView.
  138.      */
  139.     public void setBackgroundColor(Color aColor) {
  140.         if (aColor != null) {
  141.             backgroundColor = aColor;
  142.         }
  143.     }
  144.  
  145.     /** Returns the ScrollView's background Color.
  146.       * @see #setBackgroundColor
  147.       */
  148.     public Color backgroundColor() {
  149.         return backgroundColor;
  150.     }
  151.  
  152.     /** Sets the ScrollView to be transparent or opaque.
  153.       */
  154.     public void setTransparent(boolean flag) {
  155.         transparent = flag;
  156.     }
  157.  
  158.     /** Overridden to return <b>true</b> if the ScrollView is transparent.
  159.       * @see #setTransparent
  160.       */
  161.     public boolean isTransparent() {
  162.         return transparent;
  163.     }
  164.  
  165.     /** Adds <b>aScrollBar</b> to the ScrollView's Vector of Targets interested
  166.       * in scroll changes.  Whenever the ScrollView scrolls its contentView,
  167.       * it sends the ScrollBar.UPDATE command to all Targets in this
  168.       * Vector, with itself as the object.  A Target need not be a ScrollBar.
  169.       */
  170.     public void addScrollBar(Target aScrollBar) {
  171.         scrollBars.addElementIfAbsent(aScrollBar);
  172.     }
  173.  
  174.     /** Removes <b>aScrollBar</b> from its Vector of Targets interested in
  175.       * scroll changes.
  176.       * @see #addScrollBar
  177.       */
  178.     public void removeScrollBar(Target aScrollBar) {
  179.         scrollBars.removeElement(aScrollBar);
  180.     }
  181.  
  182.    /** Enables (or disables) the ScrollView to (from) send messages to Targets
  183.      * in its ScrollBar Targets Vector when the ScrollView scrolls its
  184.      * contentView.
  185.      * @see #addScrollBar
  186.      */
  187.    public void setScrollBarUpdatesEnabled(boolean flag) {
  188.         scrollBarUpdatesEnabled = flag;
  189.     }
  190.  
  191.     /** Returns <b>true</b> if ScrollBar updates are enabled.
  192.       * @see #setScrollBarUpdatesEnabled
  193.       */
  194.     public boolean scrollBarUpdatesEnabled() {
  195.         return scrollBarUpdatesEnabled;
  196.     }
  197.  
  198.    /** If ScrollBar updates are enabled, sends the ScrollBar.UPDATE command
  199.      * to all Targets in the ScrollView's ScrollBar Vector with itself as
  200.      * the object. Upon receiving this command, a ScrollBar should verify
  201.      * that its knob's size and position accurately reflect the ScrollView's
  202.      * state.
  203.      */
  204.     public void updateScrollBars() {
  205.         Target        nextScrollBar;
  206.         int             i, count;
  207.  
  208.         if (!scrollBarUpdatesEnabled) {
  209.             return;
  210.         }
  211.  
  212.         count = scrollBars.count();
  213.         for (i = 0; i < count; i++) {
  214.             nextScrollBar = (Target)scrollBars.elementAt(i);
  215.             nextScrollBar.performCommand(ScrollBar.UPDATE, this);
  216.         }
  217.     }
  218.  
  219.     /** Overridden to return this ScrollView.
  220.       */
  221.     View scrollingView() {
  222.         return this;
  223.     }
  224.  
  225.     /** Overridden to scroll the contentView such that <b>aRect</b> within the
  226.       * contentView becomes visible. Calls <b>scrollBy()</b>.
  227.       * @see #scrollBy
  228.       */
  229.     public void scrollRectToVisible(Rect contentRect) {
  230.         int     dx = 0, dy = 0;
  231.  
  232.         if (contentRect == null || contentView == null) {
  233.             return;
  234.         }
  235.  
  236. //        if (contentRect.x < 0) {
  237. //            dx = -contentRect.x;
  238. //        } else if (contentRect.maxX() > bounds.width
  239. //          && contentRect.width <= bounds.width) {
  240. //            dx = bounds.width - contentRect.maxX();
  241. //        }
  242. //        if (contentRect.y < 0) {
  243. //            dy = -contentRect.y;
  244. //        } else if (contentRect.maxY() >= bounds.height
  245. //          && contentRect.height <= bounds.height) {
  246. //            dy = bounds.height - contentRect.maxY();
  247. //        }
  248. //
  249.  
  250.         dx = positionAdjustment(bounds.width, contentRect.width, contentRect.x);
  251.         dy = positionAdjustment(bounds.height, contentRect.height, contentRect.y);
  252.  
  253.         if (dx != 0 || dy != 0) {
  254.             scrollBy(dx, dy);
  255.         }
  256.     }
  257.  
  258.     /**  This method is used by the scrollToRect method to determine the
  259.       *  proper direction and amount to move by. The ivars here are named
  260.       *  width, but this is applicable to height also. The code assumes that
  261.       *  parentWidth/childWidth are positive and childAt can be negative.
  262.       */
  263.     private int positionAdjustment(int parentWidth, int childWidth, int childAt)    {
  264. //      System.err.println("" + parentWidth + ":" + childWidth + ":" + childAt);
  265.  
  266.         //   +-----+
  267.         //   | --- |     No Change
  268.         //   +-----+
  269.         if( childAt >= 0 && childWidth + childAt <= parentWidth)    {
  270.             return 0;
  271.         }
  272.  
  273.         //   +-----+
  274.         //  ---------   No Change
  275.         //   +-----+
  276.         if(childAt <= 0 && childWidth + childAt >= parentWidth) {
  277.             return 0;
  278.         }
  279.  
  280.         //   +-----+          +-----+
  281.         //   |   ----    ->   | ----|
  282.         //   +-----+          +-----+
  283.         if(childAt > 0 && childWidth <= parentWidth)    {
  284.             return -childAt + parentWidth - childWidth;
  285.         }
  286.  
  287.         //   +-----+             +-----+
  288.         //   |  --------  ->     |--------
  289.         //   +-----+             +-----+
  290.         if(childAt >= 0 && childWidth >= parentWidth)   {
  291.             return -childAt;
  292.         }
  293.  
  294.         //   +-----+          +-----+
  295.         // ----    |     ->   |---- |
  296.         //   +-----+          +-----+
  297.         if(childAt <= 0 && childWidth <= parentWidth)   {
  298.             return -childAt;
  299.         }
  300.  
  301.         //   +-----+             +-----+
  302.         //-------- |      ->   --------|
  303.         //   +-----+             +-----+
  304.         if(childAt < 0 && childWidth >= parentWidth)    {
  305.             return -childAt + parentWidth - childWidth;
  306.         }
  307.  
  308.         return 0;
  309.     }
  310.  
  311.  
  312.     /** Moves the contentView's origin to (<b>x</b>, <b>y</b>).  If
  313.       * the ScrollView has a drawing buffer, scrolling moves as much of the
  314.       * contentView's area
  315.       * as possible and then calls <b>draw()</b> to redraw the newly exposed
  316.       * portions, otherwise just calls the contentView's <b>draw()</b> method
  317.       * to completely redraw the contentView's visible portion.
  318.       */
  319.     public void scrollTo(int x, int y) {
  320.         Rect    tmpRect = null;
  321.         int     dx, dy, myX, myY;
  322.         boolean canCopyBits;
  323.  
  324.         if (contentView == null) {
  325.             return;
  326.         }
  327.  
  328.         setClipRect(null);
  329.  
  330.         /* don't allow the content view to scroll too far */
  331.         if (x > 0 ||
  332.             bounds.width >= contentView.bounds.width) {
  333.             x = 0;
  334.         } else if (x < bounds.width - contentView.bounds.width) {
  335.             x = bounds.width - contentView.bounds.width;
  336.         }
  337.  
  338.         if (y > 0 || bounds.height >= contentView.bounds.height) {
  339.             y = 0;
  340.         } else if (y < bounds.height - contentView.bounds.height) {
  341.             y = bounds.height - contentView.bounds.height;
  342.         }
  343.  
  344.         dx = x - contentView.bounds.x;
  345.         dy = y - contentView.bounds.y;
  346.  
  347.         /* nothing to scroll */
  348.         if (dx == 0 && dy == 0) {
  349.             updateScrollBars();
  350.             return;
  351.         }
  352.  
  353.         /* if we're scrolling in only one direction, and we're allowed to
  354.          * copy bits, then figure out the newly exposed rectangle which will
  355.          * need to be drawn; someday we might get fancy and maintain two
  356.          * update rects for efficient scrolling in both dimensions
  357.          * simultaneously
  358.          */
  359.         canCopyBits = isBuffered() && drawingBufferValid;
  360.         if (canCopyBits) {
  361.             if (dx != 0 && dy == 0 && Math.abs(dx) < bounds.width) {
  362.                 if (dx < 0) {
  363.                     tmpRect = Rect.newRect(bounds.width + dx, 0,
  364.                                            -dx, bounds.height);
  365.                 } else {
  366.                     tmpRect = Rect.newRect(0, 0, dx, bounds.height);
  367.                 }
  368.             } else if (dx == 0 && dy != 0 &&
  369.                        Math.abs(dy) < bounds.height) {
  370.                 if (dy < 0) {
  371.                     tmpRect = Rect.newRect(0, bounds.height + dy,
  372.                                            bounds.width, -dy);
  373.                 } else {
  374.                     tmpRect = Rect.newRect(0, 0, bounds.width, dy);
  375.                 }
  376.             }
  377.  
  378.             if (tmpRect != null) {
  379.                 contentView.moveTo(x,y);  /** Call contentView.moveTo before changing the cliprect */
  380.                 setClipRect(tmpRect);
  381.                 Rect.returnRect(tmpRect);
  382.             } else
  383.                 contentView.moveTo(x,y);
  384.         } else
  385.             contentView.moveTo(x, y);
  386.  
  387.         if (scrollBarUpdatesEnabled) {
  388.             updateScrollBars();
  389.         }
  390.  
  391.         setDirty(true);
  392.     }
  393.  
  394.     /** Computes the contentView's new coordinates and calls <b>scrollTo()</b>.
  395.       * @see #scrollTo
  396.       */
  397.     public void scrollBy(int deltaX, int deltaY) {
  398.         if (contentView != null) {
  399.             scrollTo(contentView.bounds.x + deltaX,
  400.                      contentView.bounds.y + deltaY);
  401.         }
  402.     }
  403.  
  404.     /** Overridden to react to contentView resizes. */
  405.     public void subviewDidResize(View aSubview) {
  406.         if (aSubview != contentView) {
  407.             return;
  408.         }
  409.  
  410.         /* just scroll to the current position - scrollTo() will move
  411.          * the contentView if it has to to keep it from scrolling out of
  412.          * sight, update the scrollBars, and cause things to redraw.
  413.          */
  414.         scrollBy(0, 0);
  415.  
  416.         /* draw any newly-exposed region */
  417.         drawBackground();
  418.     }
  419.  
  420.     /** Overridden to ensure that the contentView is correctly positioned. */
  421.     public void didSizeBy(int deltaWidth, int deltaHeight) {
  422.         super.didSizeBy(deltaWidth, deltaHeight);
  423.  
  424.         /*
  425.          * make sure the contentView isn't scrolled too far in our new size
  426.          * and update the scrollBars.
  427.          */
  428.         scrollBy(0, 0);
  429.     }
  430.  
  431.     void setClipRect(Rect aRect) {
  432.         if (clipRect != null) {
  433.             Rect.returnRect(clipRect);
  434.         }
  435.         if (aRect != null) {
  436.             clipRect = Rect.newRect(aRect);
  437.         } else {
  438.             clipRect = null;
  439.         }
  440.     }
  441.  
  442.     void updateDrawingBuffer(Rect updateRect) {
  443.         if (clipRect != null && isBuffered() && !isTransparent()) {
  444.             Graphics bufferedGraphics = drawingBuffer.createGraphics();
  445.  
  446.             bufferedGraphics.setDebugOptions(shouldDebugGraphics());
  447.             if (clipRect.height != bounds.height) {
  448.                 if (clipRect.y == 0) {
  449.                     bufferedGraphics.copyArea(clipRect.x, clipRect.y,
  450.                                               clipRect.width,
  451.                                               bounds.height
  452.                                                     - clipRect.height,
  453.                                               clipRect.x, clipRect.maxY());
  454.                 } else {
  455.                     bufferedGraphics.copyArea(0, clipRect.height,
  456.                                               clipRect.width,
  457.                                               bounds.height
  458.                                                     - clipRect.height,
  459.                                               0, 0);
  460.                 }
  461.             } else {
  462.                 if (clipRect.x == 0) {
  463.                     bufferedGraphics.copyArea(clipRect.x, clipRect.y,
  464.                                               bounds.width
  465.                                                     - clipRect.width,
  466.                                               clipRect.height,
  467.                                               clipRect.maxX(), clipRect.y);
  468.                 } else {
  469.                     bufferedGraphics.copyArea(clipRect.width, 0,
  470.                                               bounds.width
  471.                                                     - clipRect.width,
  472.                                               clipRect.height,
  473.                                               0, 0);
  474.                 }
  475.             }
  476.  
  477.             bufferedGraphics.dispose();
  478.             bufferedGraphics = null;
  479.  
  480.             updateRect = new Rect(updateRect);
  481.  
  482.             // The clipRect indicates how much we scrolled and the minimum area
  483.             // necessary for a redraw is. Here we are calculating the existing
  484.             // dirtyRects for the contentView and growing the updateRect to include
  485.             // this space. This will set the clip rect large enough to hold all
  486.             // the redrawing that is needs to take place.
  487.             Rect currentDirtyRect = new Rect(0,0,0,0);
  488.             contentView.getDirtyRect(currentDirtyRect);
  489.             if(currentDirtyRect.isEmpty())  {
  490.                 updateRect.intersectWith(clipRect);
  491.             } else {
  492.                 currentDirtyRect.unionWith(clipRect);
  493.                 updateRect.intersectWith(currentDirtyRect);
  494.             }
  495.  
  496.             setClipRect(null);
  497.         }
  498.  
  499.         super.updateDrawingBuffer(updateRect);
  500.     }
  501.  
  502.     /** Overidden to perform additional clipping. */
  503.     public void computeVisibleRect(Rect aRect) {
  504.         super.computeVisibleRect(aRect);
  505.  
  506.         if (clipRect != null) {
  507.             aRect.intersectWith(clipRect);
  508.         }
  509.     }
  510.  
  511.     /** Overidden to draw the area not covered by the contentView, unless
  512.       * transparent.
  513.       */
  514.     public void drawView(Graphics g) {
  515.         Rect            graphicsClipRect;
  516.         Vector          windowClipRects;
  517.         int             width, height;
  518.  
  519.         if (isTransparent()) {
  520.             return;
  521.         } else if (contentView != null && contentView.isTransparent()) {
  522.             g.setColor(backgroundColor);
  523.             graphicsClipRect = g.clipRect();
  524.             g.fillRect(graphicsClipRect.x, graphicsClipRect.y,
  525.                        graphicsClipRect.width, graphicsClipRect.height);
  526.             return;
  527.         }
  528.  
  529.         if (contentView != null) {
  530.             width = bounds.width - contentView.bounds.width;
  531.             height = bounds.height - contentView.bounds.height;
  532.         } else {
  533.             width = bounds.width;
  534.             height = bounds.height;
  535.         }
  536.  
  537.         if (width > 0) {
  538.             g.setColor(backgroundColor);
  539.             g.fillRect(bounds.width - width, 0, width, bounds.height);
  540.         }
  541.         if (height > 0) {
  542.             g.setColor(backgroundColor);
  543.             g.fillRect(0, bounds.height - height, bounds.width, height);
  544.         }
  545.  
  546.         if (clipRect != null && isBuffered()) {
  547.             if (clipRect.y == bounds.y) {
  548.                 drawingBuffer.drawAt(g, clipRect.x, clipRect.maxY());
  549.             } else {
  550.                 drawingBuffer.drawAt(g, clipRect.x, -clipRect.height);
  551.             }
  552.         }
  553.  
  554.         /*  ALERT!  Update rect stuff temporarily removed.
  555.  
  556.         if (g.isBitmap()) {
  557.             setClipRect(null);
  558.         }
  559.  
  560.         // This appears to be here in case there is a window overlapping with
  561.         // the scroll view.  In that case you can't just do a copyArea().
  562.         // Hmmm...  A copyArea() also won't work if there is any view
  563.         // overlapping the scroll view.  ALERT!
  564.  
  565.         if (clipRect != null) {
  566.             windowClipRects = application().windowRects(clipRect, window());
  567.             if (windowClipRects != null && !windowClipRects.isEmpty()) {
  568.                 clipRect = null;
  569.             }
  570.  
  571.             Vector.returnVector(windowClipRects);
  572.         }
  573.  
  574.         // This doesn't handle horizontal scrolling.  ALERT!
  575.  
  576.         if (clipRect != null) {
  577.             if (clipRect.y == bounds.y) {
  578.                 g.copyArea(clipRect.x, clipRect.y, clipRect.width,
  579.                            bounds.height - clipRect.height,
  580.                            clipRect.x, clipRect.maxY());
  581.             } else {
  582.                 g.copyArea(bounds.x, bounds.y + clipRect.height,
  583.                            clipRect.width, bounds.height - clipRect.height,
  584.                            bounds.x, bounds.y);
  585.             }
  586.             g.sync();
  587.         }
  588.         */
  589.     }
  590.  
  591.     /** Overridden to perform post-drawing processing. */
  592.     public void drawSubviews(Graphics g) {
  593.         super.drawSubviews(g);
  594.         setClipRect(null);
  595.     }
  596.  
  597.     void drawBackground() {
  598.         Rect    tmpRect;
  599.         int     width, height;
  600.  
  601.         if (contentView != null) {
  602.             width = bounds.width - contentView.bounds.width;
  603.             height = bounds.height - contentView.bounds.height;
  604.         } else {
  605.             width = bounds.width;
  606.             height = bounds.height;
  607.         }
  608.  
  609.         tmpRect = Rect.newRect();
  610.  
  611.         if (width > 0) {
  612.             tmpRect.setBounds(bounds.width - width, 0, width, bounds.height);
  613.             addDirtyRect(tmpRect);
  614.         }
  615.         if (height > 0) {
  616.             tmpRect.setBounds(0, bounds.height - height, bounds.width, height);
  617.             addDirtyRect(tmpRect);
  618.         }
  619.  
  620.         Rect.returnRect(tmpRect);
  621.     }
  622.  
  623.     /** Overridden to pass any mouse down Event received by the ScrollView on
  624.       * to its contentView.
  625.       */
  626.     public boolean mouseDown(MouseEvent event) {
  627.         boolean                wantsEvents;
  628.  
  629.         if (contentView != null) {
  630.             wantsEvents = contentView.mouseDown(
  631.                                 convertEventToView(contentView, event));
  632.  
  633.             if (wantsEvents) {
  634.                 rootView().setMouseView(contentView);
  635.                 return true;
  636.             } else {
  637.                 return false;
  638.             }
  639.         } else {
  640.             return false;
  641.         }
  642.     }
  643.  
  644.     /** Overridden to forward the <b>acceptsDrag()</b> message to its
  645.       * contentView.
  646.       */
  647.     public DragDestination acceptsDrag(DragSession session, int x, int y) {
  648.         if (contentView != null) {
  649.             return contentView.acceptsDrag(session,
  650.                                        x - contentView.bounds.x,
  651.                        y - contentView.bounds.y);
  652.         } else {
  653.             return null;
  654.         }
  655.     }
  656.  
  657.  
  658. /* Scrollable interface */
  659.  
  660.     /** Scrollable interface method returning the appropriate bounds value.
  661.       * @see Scrollable
  662.       */
  663.     public int lengthOfScrollViewForAxis(int axis)    {
  664.         if(axis == Scrollable.HORIZONTAL)
  665.             return bounds.width;
  666.         return bounds.height;
  667.     }
  668.  
  669.     /** Scrollable interface method returning the appropriate contentView
  670.       * bounds value.
  671.       * @see Scrollable
  672.       */
  673.     public int lengthOfContentViewForAxis(int axis)   {
  674.         if(contentView == null)
  675.             return 0;
  676.         if(axis == Scrollable.HORIZONTAL)
  677.             return contentView.bounds.width;
  678.         return contentView.bounds.height;
  679.     }
  680.  
  681.     /** Scrollable interface method returning the appropriate contentView
  682.       * bounds value.
  683.       * @see Scrollable
  684.       */
  685.     public int positionOfContentViewForAxis(int axis) {
  686.         if(contentView == null)
  687.             return 0;
  688.         if(axis == Scrollable.HORIZONTAL)
  689.             return contentView.bounds.x;
  690.         return contentView.bounds.y;
  691.     }
  692.  
  693.  
  694. /* archving */
  695.  
  696.  
  697.     /** Describes the ScrollView class' information.
  698.       * @see Codable#describeClassInfo
  699.       */
  700.     public void describeClassInfo(ClassInfo info) {
  701.         super.describeClassInfo(info);
  702.  
  703.         info.addClass("netscape.application.ScrollView", 1);
  704.         info.addField(CONTENTVIEW_KEY, OBJECT_TYPE);
  705.         info.addField(BACKGROUNDC_KEY, OBJECT_TYPE);
  706.         info.addField(SCROLLERS_KEY, OBJECT_TYPE);
  707.         info.addField(SCROLLERUPDATES_KEY, BOOLEAN_TYPE);
  708.         info.addField(TRANSPARENT_KEY, BOOLEAN_TYPE);
  709.     }
  710.  
  711.     /** Encodes the ScrollView instance.
  712.       * @see Codable#encode
  713.       */
  714.     public void encode(Encoder encoder) throws CodingException {
  715.         super.encode(encoder);
  716.  
  717.         encoder.encodeObject(CONTENTVIEW_KEY, (Codable)contentView);
  718.         encoder.encodeObject(BACKGROUNDC_KEY, backgroundColor);
  719.         encoder.encodeObject(SCROLLERS_KEY, scrollBars);
  720.         encoder.encodeBoolean(SCROLLERUPDATES_KEY, scrollBarUpdatesEnabled);
  721.         encoder.encodeBoolean(TRANSPARENT_KEY, transparent);
  722.     }
  723.  
  724.     /** Decodes the ScrollView instance.
  725.       * @see Codable#decode
  726.       */
  727.     public void decode(Decoder decoder) throws CodingException {
  728.         super.decode(decoder);
  729.  
  730.         contentView = (View)decoder.decodeObject(CONTENTVIEW_KEY);
  731.         backgroundColor = (Color)decoder.decodeObject(BACKGROUNDC_KEY);
  732.         scrollBars = (Vector)decoder.decodeObject(SCROLLERS_KEY);
  733.  
  734.         scrollBarUpdatesEnabled = decoder.decodeBoolean(SCROLLERUPDATES_KEY);
  735.         transparent = decoder.decodeBoolean(TRANSPARENT_KEY);
  736.     }
  737. }
  738.